package Pakke;

//import com.apple.eawt.Application;
//import com.apple.eawt.ApplicationAdapter;
//import com.apple.eawt.ApplicationEvent;
//import sun.tools.jconsole.AboutDialog;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

/**
 * FancyTimerGUI.java
 *
 * Viser programvinduet og oppretter logikkelementer.
 *
 *
 * De utkommenterte importene har tilknyttning til AboutHandler metoden spesifikk
 * for OSX. Ikke implementert enda, derfor kommentert ut.
 *
 * @author arni
 */
public class FancyTimerGUI extends JFrame {

    private FancyTimerLogikk fancyTimerLogikk;
    private Box storRamme;
    private Box venstreSide;
    private Box hoyreSide;

    /**
     * Klasse som håndterer actioenvent kalt fra timer.
     * Blir kjørt hvert 250ms
     */
    private ActionListener taskPerformer = new ActionListener() {
      public void actionPerformed(ActionEvent e) {
          updateTicker();
          checkForAlarms();
      }
    };


    /**
     * Lager FancyTimerGUI objekt. ager FancyTimerLogikk objekt.
     * Setter opp vinduer. Starter en timer som poller FancyTimerLogikk.
     *
     */
    public FancyTimerGUI() {

        /**
         * Lytter for hovedvinduet.
         * Sørger for å oppdatere vinduet når det blir aktivert.
         * Sørger for å lukke vinduet både fra menyen og ved å trykke krysset.
         */


        WindowListener mainWindowListener = new WindowListener () {
            public void windowClosing(WindowEvent e) {
                closeMainWindow();
            }

            public void windowOpened(WindowEvent e) {
            }

            public void windowClosed(WindowEvent e) {
            }

            public void windowIconified(WindowEvent e) {
            }

            public void windowDeiconified(WindowEvent e) {
            }

            public void windowActivated(WindowEvent e) {
                updateFrames();
                validate();
            }

            public void windowDeactivated(WindowEvent e) {
            }
        };

        fancyTimerLogikk = new FancyTimerLogikk();
        Timer timer = new Timer(250, taskPerformer);
        setTitle("FancyTimer");
        setLocationByPlatform(true);
        setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        addWindowListener(mainWindowListener);
        createMenus();
        setupFrames();
        setMinimumSize(new Dimension(250, 250));
        timer.start();
    }

    /**
     * Setter opp bokselementene som utgjør områdene i GUIet.
     * To vertikale bokselementer i et horisontalt.
     */
    private void setupFrames() {
        storRamme = Box.createHorizontalBox();
        venstreSide = createVenstreside();
        hoyreSide = createHoyreside();
        add(storRamme);
        storRamme.add(venstreSide);
        storRamme.add(hoyreSide);
        pack();
    }

    /**
     * Gjør en sjekk om maskinen er en Mac. Hvis den ikke er det kjører
     * den "vanlig" kode. Hvis det er en Mac så kjører den kode for å
     * flytte menyene dit OSX pleier å ha dem.
     */
    private void createMenus(){
        if (System.getProperty("mrj.version") == null) {
            JMenuBar jmb = createNormalMenu();
             setJMenuBar(jmb);
        }else{
            System.setProperty("apple.laf.useScreenMenuBar","true");
          //System.setProperty("com.apple.mrj.application.apple.menu.about.name", "FancyTimer");
            JMenuBar jmb2 = createNormalMenu();
            setJMenuBar(jmb2);
          //new MacOSAboutHandler();
        }
    }

    /**
     * AboutHandler override for å få korrekt programnavn på About-menyen i OSX.
     * Ikke implementert.
     */
  /*
    public class MacOSAboutHandler extends Application {
        
        public MacOSAboutHandler() {
            addApplicationListener(new AboutBoxHandler());
        }

        class AboutBoxHandler extends ApplicationAdapter {
               @Override
            public void handleAbout(ApplicationEvent event) {
                new AboutDialog(new JFrame()).show();
            }
        }
    }
   * 
   */

    /**
     * Bygger menyen og kobler til en lytter.
     * @return JMenuBar
     */
    private JMenuBar createNormalMenu() {
        MenyLytter menylytter = new MenyLytter();

        JMenu filmenu = new JMenu("File");
        JMenu toolsmenu = new JMenu("Tools");

        JMenuItem filmenudel = new JMenuItem("Quit");
        JMenuItem toolsmenudel = new JMenuItem("Settings");

        filmenu.add(filmenudel);
        toolsmenu.add(toolsmenudel);

        filmenudel.addActionListener(menylytter);
        toolsmenudel.addActionListener(menylytter);

        JMenuBar menylinje = new JMenuBar();

        menylinje.add(filmenu);
        menylinje.add(toolsmenu);
        
        return menylinje;
    }

    /**
     * Kjøres hvert 250ms.
     * Sjekker om det er noen alermer som skal fyres av.
     *
     */
    private void checkForAlarms() {
        String tl[][] = fancyTimerLogikk.getTickingList();
            for(int i = 0; i < tl.length; i++) {
                if(tl[i][3].equals("1")) {
                    if (tl[i][2].trim().equals("00:00:00")){
                        fancyTimerLogikk.setActive(i, false);
                        popupAlarmWindow(i);
                    }
            }   }
    }

    /**
     * Oppdaterer hovedramma ved å tømme den og tegne den opp på nytt.
     */
    private void updateFrames() {
        storRamme.removeAll();
        setupFrames();
    }

    /**
     * Oppdaterer listen med nedtellinger ved å fjerne høyreramma og
     * tegne den opp på nytt.
     */
    private void updateTicker() {
        storRamme.remove(hoyreSide);
        hoyreSide.removeAll();
        hoyreSide = createHoyreside();
        storRamme.add(hoyreSide);
        pack();
    }

    /**
     * Lager høyreboksen med ramme (border), og legger inn aktive timere.
     * @return rightsidebox
     */
    private Box createHoyreside() {
        Box nb = Box.createVerticalBox();
        EtchedBorder bb = new EtchedBorder(EtchedBorder.LOWERED);
        EmptyBorder eb = new EmptyBorder(5, 5, 5, 5);
        CompoundBorder cb = new CompoundBorder(bb, eb);
        CompoundBorder cb2 = new CompoundBorder(eb, cb);
        nb.setBorder(cb2);
        nb.add(Box.createRigidArea(new Dimension(100,1)));
        String[][] data = fancyTimerLogikk.getTickingList();
        for(String[] s: data){
            if (s[4].equals("")){
                JLabel name = new JLabel(s[0] +" (" + s[1]+ ")");
                JLabel timeleft = new JLabel(s[2]);
                name.setAlignmentX(Component.CENTER_ALIGNMENT);
                timeleft.setAlignmentX(Component.CENTER_ALIGNMENT);
                Font fontTekst = new Font("Century Gothic", 0, 10);
                Font fontTall = new Font("Century Gothic", 0, 16);
                name.setFont(fontTekst);
                timeleft.setFont(fontTall);
                nb.add(timeleft);
                nb.add(name);
                nb.add(Box.createVerticalStrut(10));
            }
        }
        nb.add(Box.createVerticalGlue());
        return nb;
    }

    /**
     * Tegner opp venstreboksen med visuelle rammer (border), og henter inn listen
     * over favoritttimere og legger disse til i boksen.
     * @return leftbox
     */
    private Box createVenstreside() {
        Box nb = Box.createVerticalBox();
        EtchedBorder bb = new EtchedBorder(EtchedBorder.LOWERED);
        EmptyBorder eb = new EmptyBorder(5, 5, 5, 5);
        CompoundBorder cb = new CompoundBorder(bb, eb);
        CompoundBorder cb2 = new CompoundBorder(eb, cb);
        nb.setBorder(cb2);
        String[][] data = fancyTimerLogikk.getFavouriteList();
        int i = 0;
        for (String [] s: data) {
            JButton mat = new JButton(s[0]);
            mat.setAlignmentX(Component.CENTER_ALIGNMENT);
            TimerKnappeLytter tkl = new TimerKnappeLytter(i);
            mat.addActionListener(tkl);
            nb.add(mat);
            JLabel valg = new JLabel(s[1]);
            Font font = new Font("Verdana", 0, 9);
            TimerTekstLytter ttl = new TimerTekstLytter(i);
            valg.setFont(font);
            valg.addMouseListener(ttl);
            valg.setAlignmentX(Component.CENTER_ALIGNMENT);
            nb.add(valg);
            i++;
        }
        nb.add(Box.createVerticalGlue());
        return nb;
    }

    /**
     * Funksjon som fyrer av et popup-vindu når en alarm har gått.
     * @param timerID
     */
    private void popupAlarmWindow(int i) {
        String[] dti = fancyTimerLogikk.getDetailedTimerinfo(i);
        JFrame alarmvindu = new JFrame();
        alarmvindu.setResizable(false);
        alarmvindu.setLocationByPlatform(true);
        JPanel panel = new JPanel();
        JLabel infotekst = new JLabel(dti[0] + " " + dti[1] +" er nå ferdig.");
        JButton snooze = new JButton("Snooze 5 min");
        JButton removeAlarm = new JButton("Remove alarm");
        TimerAlarmKnappeLytter takl = new TimerAlarmKnappeLytter(i);
        snooze.addActionListener(takl);
        removeAlarm.addActionListener(takl);
        panel.add(infotekst);
        panel.add(snooze);
        panel.add(removeAlarm);
        alarmvindu.add(panel);
        alarmvindu.setVisible(true);
        alarmvindu.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        TimerWindowListener twl = new TimerWindowListener(i);
        alarmvindu.addWindowListener(twl);
        alarmvindu.pack();
        fancyTimerLogikk.startNotification(i);
    }

    /**
     * Egen versjon av ActionListener, som lagrer en ID.
     * Kan da binde hver knapp til en egen actionlistener for eklere samspill.
     */
    private class TimerKnappeLytter implements ActionListener {
        private int id;

        /**
         * Konstruktøren til TimerKnappeLytter
         * @param timerDataID
         */
        public TimerKnappeLytter(int id ) {
            super();
            this.id = id;
        }

        /**
         * Lager en timer i logikken med id til den knappen som ble trykt på.
         * @param actionEvent
         */
        public void actionPerformed(ActionEvent actionEvent) {
             fancyTimerLogikk.createTimer(id);
        }
    }

    /**
     * Lytter for knappene i alarmvinduet som kommer opp.
     *
     */
    private class TimerAlarmKnappeLytter implements ActionListener {
        private int id;

        /**
         * Konstruktøren til TimerAlarmKnappelytter
         * @param timerId
         */
        public TimerAlarmKnappeLytter(int id ) {
            super();
            this.id = id;
        }

        /**
         * Utfører handlinger basert på hvilken knapp som blir trykt i alarmvinduet.
         * Kan enten snooze eller fjerne en alarm.
         * @param actionEvent
         */
        public void actionPerformed(ActionEvent actionEvent) {
            if (actionEvent.getActionCommand().equals("Snooze 5 min")) {
                fancyTimerLogikk.snoozeTimer(id, 300000);
                JButton b = (JButton)actionEvent.getSource();
                JPanel p = (JPanel)b.getParent();
                JFrame f = (JFrame)p.getParent().getParent().getParent().getParent();
                f.dispose();
                fancyTimerLogikk.stopNotification(id);
                fancyTimerLogikk.setActive(id, true);
            }
            if (actionEvent.getActionCommand().equals("Remove alarm")) {
                JButton b = (JButton)actionEvent.getSource();
                JPanel p = (JPanel)b.getParent();
                JFrame f = (JFrame)p.getParent().getParent().getParent().getParent();
                stengAlarmVindu(id, f);
            }
        }
    }

    /**
     * Lytter som følger med om man trykker på teksten under timerdataknappene i venstrevinduet
     */
    private class TimerTekstLytter implements MouseListener {
        private int id;

        /**
         * Konstruktøren til TimerTekstLytter
         * @param timerDataId
         */
        public TimerTekstLytter(int id) {
            super();
            this.id = id;
        }

        /**
         * @param e
         */
        public void actionPerformed(MouseEvent e) {
        }

        /**
         * Fyrer av en popup når man trykker på en jlabel
         * @param e
         */
        public void mouseClicked(MouseEvent e) {
            if(e.getButton() == MouseEvent.BUTTON1) {
                 displayAlternativerPopup(id, e.getComponent(), e.getX(), e.getY());
            }

        }

        public void mousePressed(MouseEvent e) {
        }

        public void mouseReleased(MouseEvent e) {
        }

        public void mouseEntered(MouseEvent e) {
        }

        public void mouseExited(MouseEvent e) {
        }

    }

    /**
     * Klasse som lytter på hvilket valg som blir gjort i popupmenyen som kommer
     * når man trykker en tekst i venstrevinduet. Har lagret timerdataID og alternativID
     * for å slippe så mye traversering av objekter.
     */
    private class TimerAlternativerListeLytter implements ActionListener {
        int tTd;
        int aId;

        /**
         * Konstruktøren til TimerAlternativerListeLytter
         * @param timerDataID
         * @param alternativID
         */
        public TimerAlternativerListeLytter(int tTd, int aId) {
            super();
            this.tTd = tTd;
            this.aId = aId;
        }

        /**
         * Oppdaterer fancyTimerLogikk med valg som blir gjort
         * Oppdaterer viduene.
         * Lagrer data på disk.
         * @param e
         */
        public void actionPerformed(ActionEvent e) {
            fancyTimerLogikk.setAlternative(tTd, aId);
            updateFrames();
            fancyTimerLogikk.saveAllData();
        }

    }

    /**
     * Vinduslytter for alarmvinduet som spretter opp.
     *
     */
    private class TimerWindowListener implements WindowListener {
        private int id;

        /**
         * Konstruktøren til TimerWindowListener
         * @param id
         */
        public TimerWindowListener(int id) {
            super();
            this.id = id;
        }

        public void windowOpened(WindowEvent e) {
        }

        /**
         * Hvis vinduet blir lukket kjører stengAlarmVindu.
         * @param e
         */
        public void windowClosing(WindowEvent e) {
           JFrame jf = (JFrame)e.getSource();
           stengAlarmVindu(id, jf);
        }

        public void windowClosed(WindowEvent e) {
        }

        public void windowIconified(WindowEvent e) {
        }

        public void windowDeiconified(WindowEvent e) {
        }

        public void windowActivated(WindowEvent e) {

        }

        public void windowDeactivated(WindowEvent e) {
        }

    }


    /**
     * Funksjon for å stenge programmet
     */
    private void closeMainWindow() {
        this.dispose();
        System.exit(0);
    }

    /**
     * Funksjon for å lukke alarmvindu og slå av alarm. Blir kjørt fra
     * timer og knappelytter. Enten ved å trykke slå av alarm eller ved å trykke x-en i hjørnet.
     * @param id
     * @param f
     */
    private void stengAlarmVindu(int id, JFrame f) {
        f.dispose();
        fancyTimerLogikk.hideTimer(id);
        fancyTimerLogikk.stopNotification(id);
    }

    /**
     * Viser en popup når man trykker på en jlabel under knapper i venstrevinduet.
     * Koordinater for musetrykket og hvilken container det hele skjer i er med som argumenter.
     * @param timerDataID
     * @param c
     * @param x
     * @param y
     */
    private void displayAlternativerPopup(int timerID, Component c, int x, int y) {
            JPopupMenu jpm = new JPopupMenu();
            String[][] timerAlternativer = fancyTimerLogikk.getAlternatives(timerID);
            int aId = 0;
            for (String[] s: timerAlternativer) {
                JMenuItem jmi = new JMenuItem(s[0] + " " + s[1]);
                jmi.addActionListener(new TimerAlternativerListeLytter(timerID, aId));
                jpm.add(jmi);
                aId++;
            }
            jpm.show(c, x, y);
        }

    /**
     * Lytter for menyen.
     *
     */
    private class MenyLytter implements ActionListener {
        public void actionPerformed(ActionEvent a) {
            String valg = a.getActionCommand();
            if(valg.equals("Quit")) {

                closeMainWindow();
            } else if(valg.equals("Settings")) {
                SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                       showSettings();
                }
            });}
        }
    }

    /**
     * Starter settingsvinduet
     */
    private void showSettings(){
        JFrame ogp = new FancyTimerGuiSettings(fancyTimerLogikk, this);
        ogp.validate();
        Dimension minDim = new Dimension(600, 350);
        //Dimension maxDim = new Dimension(600, 350);
        ogp.setMinimumSize(minDim);
        //frame.setMaximumSize(maxDim);
        ogp.setResizable(false);
        ogp.setVisible(true);
        setEnabled(false);
    }


}